package editor
{
	import Classes.CLoader;
	import Classes.pi_events;
	
	import UIFree.ObjectEvent;
	import UIFree.uif_component;
	import UIFree.uif_draw;
	import UIFree.uif_ecomponent;
	
	import flash.display.BitmapData;
	import flash.display.DisplayObject;
	import flash.events.Event;
	import flash.geom.ColorTransform;
	import flash.geom.Matrix;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	import flash.net.URLRequest;
	import flash.utils.ByteArray;
	
	import templates.pi_effects;
	
	public class pi_cardbody extends uif_ecomponent {
/*
Список функций распознования расширеных параметров из строки параметров, 
можно дополнять извне. Соответственно должен быть с таким же именем класс-сервис,
реализующий функционал в списке serviceClass.

В классе сервиса должен быть конструктор вида (cardObject: pi_cardbody, serviceParams: Array)
и метод dispose() - реализующий уничтожение сервиса

*/		
		public static var serviceClass: Object = {};
		
		protected var _maskInfo		: pi_maskInfo;
		protected var _photo		: CLoader;
		protected var _mask			: pi_source;
		protected var _photoMatrix	: Matrix;
		protected var _services		: Object;
		protected var _colorsExt	: ColorTransform;
		protected var _tmplColors	: ColorTransform;
		private var _photoModified	: Boolean;
		
		protected const STOREIDCARD: String = 'strcp';
		
		
		public function pi_cardbody(parent:uif_component,
									ax: int=0, ay: int=0,
									awidth: int=0, aheight: int=0, styleName: String='') {
			super(parent, ax, ay, awidth, aheight, styleName);
			_colorsExt  = new ColorTransform();
			_tmplColors = new ColorTransform();
			_services	= new Object();
			_photo 		= new CLoader(this, '', doLoadPhoto);
			_mask		= new pi_source(this);
			_photoMatrix	= new Matrix();
			addEvent(Event.COMPLETE, doLoadMask, _mask.source.contentLoaderInfo);
			addEvent(pi_events.UPDATECARD, doReselect);
			_photo.visible 	= false;
			_photoModified	= true;
			maskResize();
		}
		
		public function get photoModified(): Boolean {
			return _photoModified;
		}
		
		public function set photoModified(a_set: Boolean): void {
			if (_photoModified != a_set) doPhotoModified(a_set);
		}
		
		protected function doPhotoModified(a_set: Boolean): void {
			if (!a_set) doStorePhoto(); 
			_photoModified = a_set;
			if (_photoModified) doRestorePhoto();
			dispatchEvent(new Event(pi_events.CHANGEMODIFIED));
		}
		
		protected function doStorePhoto(): void {
			app.dispatchEvent(new ObjectEvent(pi_events.STORE, STOREIDCARD));
		}
		
		protected function doRestorePhoto(): void {
			app.dispatchEvent(new ObjectEvent(pi_events.RESTORE, STOREIDCARD));
		}
		
		protected function doDelstorePhoto(): void {
			app.dispatchEvent(new ObjectEvent(pi_events.DELSTORE, STOREIDCARD));
		}
		
		public function get colorsExt(): ColorTransform {
			return _colorsExt;
		}
		
		public function set colorsExt(a_newColors: ColorTransform): void {
			setColorExt(a_newColors);
		}
		
		protected function setColorExt(a_newColors: ColorTransform): void {
			_colorsExt = a_newColors;
			refresh();
		}
		
		public function applyEXTValue(EXTName: String, values: String): void {
			if (values) {
				if (!maskInfo.extend) maskInfo.extend = new Object();	
				maskInfo.extend[EXTName] = [EXTName, values];
			} else delete(maskInfo.extend[EXTName]);	
		}
		
		public function get tmplColors(): ColorTransform {
			return _tmplColors;
		}
		
		protected function doReselect(event: ObjectEvent): void {
			if (event.object is pi_photo) {
				applyPhotoMatrix(event.object.rect.getMatrix());
			} else applyPhotoMatrix(photoMatrix);
		}
		
		protected function maskResize(): void {
			var inner: Rectangle = getInner();
			_mask.resize(inner.width, inner.height);
		}
		
		override protected function updateBounds(): uif_component {
			super.updateBounds();
			if (_mask) maskResize();
			return this;
		}
		
		public function get card_photo(): CLoader {
			return _photo;
		}
		
		public function set card_photo(a_loader : CLoader): void {
			resetPhoto(a_loader);
		}
		
		public function get card_mask(): pi_source {
			return _mask;
		}
		
		public function get loaded(): Boolean {
/*			if (pj.requireLoaded == photo_inject.MASK_LOAD_ONLY)
				return card_mask.source.loaded;
			else {
				if (!pj.editor) return card_mask.source.loaded && card_photo.loaded;
				else return card_mask.source.loaded;
			}*/
			return card_mask.source.loaded && card_photo.loaded;
		}
		
		protected function doLoadPhoto(e: Event): void {
			resetPhoto(_photo);
			doLoadedComponent();
		}
		
		protected function doLoadedComponent(): void {
			if (loaded) app.dispatchEvent(new ObjectEvent(pi_events.COMPLETEFULLLOAD, this));
		}
		
		public function refresh(): void {
			updateFromInfo();
		}
		
		protected function updateFromInfo(): void {
/*			trace((maskInfo.pos?maskInfo.pos.toString():'') + 
					(maskInfo.r3d?(' ' + maskInfo.r3d.toString()):''));*/
		}
		
		public function get editing(): Boolean {
			return parent is pi_editor;
		}
		
		protected function doLoadMask(e: Event): void {
			app.dispatchEvent(new ObjectEvent(pi_events.COMPLETELOADCARD, this));
			doLoadedComponent();
			if (_maskInfo.pos && editing) app.dispatchEvent(new ObjectEvent(pi_events.SETPHOTORECT, new Point(_maskInfo.pos.width, _maskInfo.pos.height)));
			refresh();
			trace(_mask.source.contentLoaderInfo.width + 'x' + _mask.source.contentLoaderInfo.height + '\n');
		}
		
		protected function resetPhoto(a_photo: CLoader): void {
			_photo = a_photo;
			refresh();
		}
		
		public function applyPhotoMatrix(matrix: Matrix): void {
			if (_photoModified) {
				if (matrix) {
					_photoMatrix = matrix;
					app.dispatchEvent(new ObjectEvent(pi_events.APPLYPHOTOMATRIX, this));
				}
				refresh();
			}
		}
		
		public function get pj(): photo_inject {
			return app as photo_inject;
		}
		
		public function packInfo(): String {
/*			var result: String = '';
			if (_maskInfo && photoMatrix) {
				var mat: Matrix = photoMatrix;
				var matStr: String = mat.a + ',' + mat.b + ',' + mat.c + ',' + mat.d + ',' + mat.tx + ',' + mat.ty;
				result = _maskInfo.id + '~' + matStr;
				if (_photo && _photo.loaded) result += '~' + _photo.sourceUrl.replace('http://', '');
				result += packExtend();
			}*/
			return getPackInfo(photoMatrix, (_photo && _photo.loaded)?_photo.sourceUrl:'');
		}
		
		protected function getPackInfo(a_photoMatrix: Matrix, photoURL: String=''): String {
			var result: String = '';
			if (_maskInfo && a_photoMatrix) {
				var mat: Matrix = a_photoMatrix;
				var matStr: String = mat.a + ',' + mat.b + ',' + mat.c + ',' + mat.d + ',' + mat.tx + ',' + mat.ty;
				result = _maskInfo.id + '~' + matStr;
				if (photoURL) result += '~' + (photoURL?photoURL.replace('http://', ''):'');
				result += packExtend();
			}
			return result;
		}
		
		protected function prepareExtendsFromSend(postProc: Function): void {
			var waitCount: int = 0;
			function doPostExtendPrepare(): void {
				waitCount--;
				if (waitCount == 0) postProc();
			}
			
			if (_maskInfo.extend) {
				for (var property: String in _maskInfo.extend)
					if (pj.extendObjects[property].hasOwnProperty('createFromSend')) {
						pj.extendObjects[property].createFromSend(doPostExtendPrepare);
						waitCount++;
					}
				if (waitCount == 0) postProc();
			} else postProc();
		}
		
		public function createFromSend(sendProc: Function): void {
			if ((_photo.isDynamic) || (!pj.albumAssessFromSend(pj.photoData))) { 
				// Если фотку подгрузили с компа, тогда сохраняем на сервере в виде JPG файл, и тогда только отправляем
				pj.manager.collectJPG(JPGPhotoFromCard(photoFromSendCard()), function(fileName: String): void {
					if (!fileName) pj.ErrorMyServer();
					else prepareExtendsFromSend(function(): void {
						sendProc(getPackInfo(new Matrix(), fileName));
					});
				}, 'from_card', false, false);
			} else prepareExtendsFromSend(function(): void {
				sendProc(packInfo());
			});
		}
		
		protected function photoFromSendCard(): DisplayObject {
			return _photo;
		} 
		
		protected function JPGPhotoFromCard(a_photo: DisplayObject): ByteArray {
			var psize: Point = new Point(maskInfo.pos.width, maskInfo.pos.height);
			var pbmd: BitmapData = new BitmapData(psize.x, psize.y, false);
			pbmd.draw(a_photo, photoMatrix);
			var ba: ByteArray = pj.encodeFromJPG(pbmd);
			pbmd.dispose();
			return ba;
		}
		
		protected function packExtend(): String {
			var result: String = '';
			if (_maskInfo.extend) {
				for (var index: String in _maskInfo.extend) {
					if (index != 'filters')
						result += '~' + _maskInfo.extend[index].toString();
				}
			}
			return result;
		}
		
		public function infoFromCollector(): String {
			var mat: Matrix = photoMatrix;
			var matStr: String = mat.a + ',' + mat.b + ',' + mat.c + ',' + mat.d + ',' + mat.tx + ',' + mat.ty;
			return _maskInfo.toString() + '&matrix=' + matStr + 
					'&img=' + ((_photo && _photo.loaded)?_photo.sourceUrl.replace('http://', ''):'');
		}
		
		public static function union(obj1: Object, obj2: Object): Object {
			var result: Object = uif_draw.union(obj1, obj2);
			if (obj1 && obj1.extend && obj2 && obj2.extend) {
				result.extend = uif_draw.union(obj1.extend, obj2.extend);
			}
			return result;
		}
		
		public static function _parseMSG(params: Array): Object {
			return params;
		}
		
		public static function _parseEXT(extend: Array, result: Object): void {
			result.extend = {};
			for (var i: int=0; i< extend.length; i++) {
				var params: Array = extend[i].split(',');
				if (params.length > 1) result.extend[params[0]] = params;
			}
		}
		
		public static function parseEffect(param: String): int {
			var result: int = parseInt(param);
			if ((result.toString().length != param.length) ||
				(pi_effects.effectIndex(result) == -1)) 
				result = 0;
			return result;
		}
		
		public static function unpackInfo(_info: String): Object {
			if (_info) {
				var res: Array = _info.split('~');
				if ((res.length > 1) && (parseInt(res[0]) > 0)) {
					var result: Object = {cardID: res[0], matrix: res[1]};
					
					if (res.length > 2) {
						if (parseEffect(res[2])) result.effectID = parseEffect(res[2]);
						else {
							result.photo = res[2];
							if (res.length > 3) {
								_parseEXT(res.slice(3), result);
								result.effectID = parseEffect(res[res.length - 1]);
							}
						}
					}
					return result;
				} else if ((res.length == 1) && (res[0] is String)) {
					var asSID: Array = res[0].split(',');
					if (asSID[0] == 'sid') return {sid:asSID[1]}
					else if (res[0].indexOf('http://') == 0) return {photo_url: res[0]};
						else {
							var info: Object = new Object();
							for (var i: int=0;i<res.length; i++) {
								var par: Array = res[i].split(',');
								if (par.length > 1) info[par[0]] = par[1];
							}
							return info;
						};
				}
			}
			return null
		}
		
		public function get photoMatrix(): Matrix {
			return _photoMatrix;
		}
		
		public function bmpContent(): Boolean {
			if (_mask && _mask.source.sourceUrl && _mask.source.loaded) {
				var ext: Array = _mask.source.sourceUrl.split('.');
				return (ext[ext.length - 1] == 'png') || _maskInfo.jpg;
			} else return false;
		}
		
		public function get maskInfo(): pi_maskInfo {
			return _maskInfo;
		}
		
		protected function createFilters(a_filters: Object): void {
			
			var p_filters: Array = _photo.filters;
			for (var filterClass: String in a_filters) {
				p_filters.push(new pi_data.filters[filterClass](a_filters[filterClass]));
			}
			_photo.filters = p_filters;
		}
		
		public function get cardBounds(): Rectangle {
			return new Rectangle(card_mask.source.x, card_mask.source.y, card_mask.source.width, card_mask.source.height);
		}
		
		public function unloadAll(): void {
			doDelstorePhoto();
			disposeServices();
			_mask.source.unload();
			_photo.unload();
		}
		
		override public function dispose(): void {
			unloadAll();
			super.dispose();
		}
		
		public function disposeServices(): void {
			for (var i: String in _services) {
				_services[i].dispose();
				delete(_services[i]);
			}
		}
		
		public function get services(): Object {
			return _services;
		}
		
		protected function loadMask(): void {
			_mask.loadSource(_maskInfo.url);
		}
		
		protected function setPhotoMatrix(mat: Object): void {
			var matA: Array = mat.split(',');
			_photoMatrix = new Matrix(matA[0], matA[1], matA[2], matA[3], matA[4], matA[5]);		
		}
		
		protected function resetFromPhoto(): void {
			function l_doLoad(e: Event): void {
				_photo.contentLoaderInfo.removeEventListener(Event.COMPLETE, l_doLoad);
				resetFromMask();
			}
			_photo.contentLoaderInfo.addEventListener(Event.COMPLETE, l_doLoad);
			_photo.load(new URLRequest('http://' + _maskInfo.photo));
/*			var tmp: CLoader = new CLoader(null, _maskInfo.photo, function(e: Event): void {
				tmp.duplicate(_photo);
				tmp.unload();
				resetFromMask();
			}, 0, 0, new LoaderContext(true, ApplicationDomain.currentDomain));*/
//			loadPhoto(_maskInfo.photo, _photo);
		} 
		
		protected function resetFromMask(): void {
			disposeServices();
			_mask.source.unload();
			
			if (_maskInfo.photoMatrix) setPhotoMatrix(_maskInfo.photoMatrix);
			_photo.visible = false;
			loadMask();
			_photo.transform.colorTransform = _maskInfo.colors;
			if (_maskInfo.filters) createFilters(_maskInfo.filters);
			else _photo.filters = new Array();

			if (_maskInfo.extend) {
				// Просматриваем сервисы, если есть параметр относящийся к сервису, тогда инициализируем
				for (var property: String in _maskInfo.extend) {
					if (serviceClass.hasOwnProperty(property))
						_services[property] = new serviceClass[property](this, _maskInfo.extend[property]);
				}
			}
		}
			
		public function setMaskInfo(a_maskInfo: pi_maskInfo): void {
			_maskInfo = a_maskInfo;
			if (a_maskInfo.photo) resetFromPhoto(); 
			else resetFromMask();
		}
	}
}